package com.atguigu.spzx.pay.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.alipay.api.response.AlipayTradeWapPayResponse;
import com.atguigu.spzx.feign.orderInfo.OrderInfoFeignClient;
import com.atguigu.spzx.feign.product.ProductFeignClient;
import com.atguigu.spzx.model.dto.product.SkuSaleDto;
import com.atguigu.spzx.model.entity.order.OrderInfo;
import com.atguigu.spzx.model.entity.order.OrderItem;
import com.atguigu.spzx.model.entity.pay.PaymentInfo;
import com.atguigu.spzx.model.entity.user.UserInfo;
import com.atguigu.spzx.pay.mapper.PaymentInfoMapper;
import com.atguigu.spzx.pay.properties.AlipayProperties;
import com.atguigu.spzx.pay.service.AlipayService;
import com.atguigu.spzx.service.utils.AuthContextUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.SneakyThrows;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * ClassName: AlipayServiceImpl
 * Package: com.atguigu.spzx.pay.service.impl
 * Description:
 *
 * @Author 刘强
 * @Create 2024/7/19 18:10
 * @Version 1.0
 */
@Service
public class AlipayServiceImpl implements AlipayService {
    @Resource
    private AlipayClient alipayClient;
    @Resource
    private AlipayProperties alipayProperties;
    @Resource
    private OrderInfoFeignClient orderInfoFeignClient;

    @Resource
    private PaymentInfoMapper paymentInfoMapper;
    @Resource
    private ProductFeignClient productFeignClient;

    /**
     * 去支付  -> 返回一个支付宝的支付页面  -> 表单字符串
     *
     * @param orderNo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String submitAlipay(String orderNo) {
        // 1. 保存交易流水日志  -> 目的是异步回调接口对账
        OrderInfo orderInfo = orderInfoFeignClient.getByOrderNo(orderNo);
        UserInfo userInfo = AuthContextUtils.get();
        PaymentInfo paymentInfo = new PaymentInfo();
        paymentInfo.setUserId(userInfo.getId());
        paymentInfo.setOrderNo(orderNo);
        paymentInfo.setPayType(2);
        paymentInfo.setAmount(orderInfo.getTotalAmount());
        String content = getPaymentInfoContent(orderInfo);
        paymentInfo.setContent(content);
        paymentInfo.setPaymentStatus(0);
        paymentInfo.setCreateTime(new Date());
        paymentInfo.setUpdateTime(new Date());
        paymentInfoMapper.save(paymentInfo);
        // 2. 调用Alipay服务的支付接口
        // 3. 封装返回值
        return getAlipayFormString(orderNo);
    }

    /**
     * 获取交易流水日志的内容
     * @param orderInfo
     * @return
     */
    private  String getPaymentInfoContent(OrderInfo orderInfo) {
        List<OrderItem> orderItemList = orderInfo.getOrderItemList();
        StringBuilder content = new StringBuilder();
        if(!CollectionUtils.isEmpty(orderItemList)){
            for (int i = 0 ;i<orderItemList.size();i++) {
                OrderItem orderItem = orderItemList.get(i);
                if(i==orderItemList.size()-1){
                    content.append(orderItem.getSkuName());
                }
                content.append(orderItem.getSkuName()).append(" ");
            }
        }else {
            return "";
        }
        return content.toString();
    }

    /***
     * 支付宝的异步通知
     * @param paramMap
     * @param request
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String callback(Map<String, String> paramMap, HttpServletRequest request) {
        try {
            // 1. 一次验签 -> 保证数据的安全性
            boolean flag = AlipaySignature.rsaCheckV1(paramMap, alipayProperties.getAlipayPublicKey(), alipayProperties.getCharset(), alipayProperties.getSignType());
            // 2. 二次验签 -> 保证数据的正确性
            String appId = paramMap.get("app_id");
            String orderNo = paramMap.get("out_trade_no");
            String outTradeNo = paramMap.get("trade_no");
            String totalAmount = paramMap.get("total_amount");
            OrderInfo orderInfo = null;
            if(!flag){
               return "fail";
            }
            orderInfo = orderInfoFeignClient.getByOrderNo(orderNo);
            if(!orderInfo.getTotalAmount().equals(totalAmount) ){
                return "fail";
            }
            // 3. 保证接口的幂等性
            PaymentInfo paymentInfo = paymentInfoMapper.getByOrderNo(orderNo);
            if(paymentInfo.getPaymentStatus().intValue() == 1){
                return "success";
            }
            // 4. 更新交易流水日志
            paymentInfo.setOutTradeNo(outTradeNo);
            paymentInfo.setPaymentStatus(1);
            paymentInfo.setCallbackTime(new Date());
            paymentInfo.setCallbackContent(JSON.toJSONString(paramMap));
            paymentInfo.setUpdateTime(new Date());
            paymentInfoMapper.updateById(paymentInfo);
            // 5. 更新库存和销量
            List<OrderItem> orderItemList = orderInfo.getOrderItemList();
            if(CollectionUtils.isEmpty(orderItemList)){
                return "fail";
            }
            List<SkuSaleDto> skuSaleDtoList = orderItemList.stream().map(orderItem -> {
                SkuSaleDto skuSaleDto = new SkuSaleDto();
                skuSaleDto.setSkuId(orderItem.getSkuId());
                skuSaleDto.setNum(orderItem.getSkuNum());
                return skuSaleDto;
            }).collect(Collectors.toList());
            productFeignClient.updateStockAndSaleNum(skuSaleDtoList);
            // 6. 更新订单状态
            orderInfoFeignClient.updateOrderStatus(1);
            // 7. 保存订单日志
            orderInfoFeignClient.saveOrderLog(orderInfo.getId(),1);
            return "success";
        } catch (AlipayApiException e) {
            return "fail";
        }
    }

    @SneakyThrows
    private String getAlipayFormString(String orderNo)  {
        AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
//异步接收地址，仅支持http/https，公网可访问
        request.setNotifyUrl(alipayProperties.getNotifyUrl());
//同步跳转地址，仅支持http/https
        request.setReturnUrl(alipayProperties.getReturnUrl());
/******必传参数******/
        JSONObject bizContent = new JSONObject();
//商户订单号，商家自定义，保持唯一性
        bizContent.put("out_trade_no", orderNo);
//支付金额，最小值0.01元 -> 根据订单编号查询订单总金额
        bizContent.put("total_amount", 0.01);
//订单标题，不可使用特殊符号
        bizContent.put("subject", "订单支付");

/******可选参数******/
//手机网站支付默认传值QUICK_WAP_WAY
        bizContent.put("product_code", "QUICK_WAP_WAY");

        request.setBizContent(bizContent.toString());
        AlipayTradeWapPayResponse response = alipayClient.pageExecute(request, "POST");
// 如果需要返回GET请求，请使用
// AlipayTradeWapPayResponse response = alipayClient.pageExecute(request,"GET");
        String pageRedirectionData = response.getBody();
        System.out.println(pageRedirectionData);

        if (response.isSuccess()) {
            System.out.println("调用成功");
        } else {
            System.out.println("调用失败");
        }
        return pageRedirectionData;
    }
}
